package com.ruoyi.team.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.team.domain.vo.StockBillVo;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.team.mapper.StockBillMapper;
import com.ruoyi.team.domain.StockBill;
import com.ruoyi.team.service.IStockBillService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 出入库单据Service业务层处理
 *
 * @author xiaowai
 * @date 2022-11-27
 */
@Service
public class StockBillServiceImpl extends ServiceImpl<StockBillMapper, StockBill> implements IStockBillService {

    /**
     * 查询出入库单据列表
     *
     * @param stockBill 出入库单据
     * @return 出入库单据
     */
    @Override
    public List<StockBill> selectStockBillList(StockBill stockBill) {
        List<StockBill> stockBills = getBaseMapper().selectStockBillList(stockBill);

        //查询出stockBill集合对象,遍历出入库单据,然后根据id,在出入库单据明细中去查找每一个单据的数据
        for (StockBill bill : stockBills) {

            List<StockBillVo> list = getBaseMapper().selectByStockBillId(bill.getId());
            //设置总数量
            Long total = 0L;
            //设置总金额
            BigDecimal money = BigDecimal.ZERO;
            //遍历这个集合得到每种物品的数量,和总价
            for (StockBillVo stockBillVo : list) {
                //得到数量
                total += Long.parseLong(stockBillVo.getNumber());
                //得到总金额
                BigDecimal multiply = BigDecimal.valueOf(Double.parseDouble(stockBillVo.getPrice())).multiply(BigDecimal.valueOf(Double.parseDouble(stockBillVo.getNumber())));
                money = money.add(multiply);
            }
            Map<String, Object> map = new HashMap<>();
            map.put("total",total);
            map.put("money",money);

            bill.setParams(map);
        }

        return stockBills;
    }

    @Transactional(rollbackFor = ServiceException.class)
    @Override
    public boolean out(StockBill stockBill) {

        //设置操作人
        stockBill.setOperatorId(SecurityUtils.getUserId());
        //设置操作时间
        stockBill.setOperateDate(new Date());

        //获取前端传来的参数,调用父类的保存方法保存
        boolean save = super.save(stockBill);

        //获取前端传来的数据获取物品的id,物品的价钱,数量
        StockBillVo[] goods = stockBill.getGoods();
        //遍历物品数组
        for (StockBillVo good : goods) {
            //调用mapper方法在关系表中增加关系
            //在出入库单据明细表中插入单据id,物品id,物品的价钱,数量
            getBaseMapper().insertRelationToGoods(stockBill, good);
            //需要增加仓库里面的物品的数量
            //根据物品的id查询出仓库物品的数量
            //获取仓库id
            Long statusId = stockBill.getStoreId();
            Long number = getBaseMapper().selectGoodsInStore(statusId, good);
            //判断number是否为空
            if (number == null || number == 0) {
                //仓库中物品数量为0,或者为空,提示仓库中该物品数量为空,无法操作
                throw new ServiceException("仓库中该物品数量为空,无法操作");

            } else {
                //如果有数量,那么就查询出仓库里面的物品数量,然后判断仓库里面的数量
                if (number < Long.parseLong(good.getNumber())) {
                    //如果仓库里卖的物品数量不够,就提示仓库数量不足,无法出库
                    throw new ServiceException("仓库数量不足,无法出库");
                } else {
                    //如果仓库数量足够的话,就可以出库
                    //得到实际物品的数量
                    Long sum = number - Long.parseLong(good.getNumber());
                    //根据物品的id所在仓库里面修改数量
                    getBaseMapper().updateGoodsInStore(statusId, good.getId(), sum);
                }
            }
        }
        return save;
    }

    @Override
    public boolean removeBatchById(Long id) {
        //通过id在出入库单据中查询出当前出入库单
        StockBill stockBill = getBaseMapper().selectById(id);
        //获取订单放入的仓库id
        Long storeId = stockBill.getStoreId();
        //判断这个出入库单是出库还是入库 0,入库 1,出库
        if (stockBill.getType().equals(0)) {
            //如果是入库,那么就需要将之前往仓库里面的存入的物品数量进行减少
            //通过入库单的id在出入库单据明细中,查找出哪些商品进行了入库
            List<StockBillVo> list = getBaseMapper().selectGoodsByBillId(id);
            for (StockBillVo stockBillVo : list) {
                //查询出当前仓库的库存数量
                Long number = getBaseMapper().selectGoodsInStore(storeId, stockBillVo);
                //如果仓库中的数量如果不够减少的话,就需要提示作废操作无法执行
                if (Long.parseLong(stockBillVo.getNumber()) > number) {
                    throw new ServiceException("库存不足无法执行作废操作");
                }
                //如果数量够的话,就执行修改数量的操作
                Long sum = number - Long.parseLong(stockBillVo.getNumber());

                //根据物品的id所在仓库里面修改数量
                getBaseMapper().updateGoodsInStore(storeId, stockBillVo.getId(), sum);
            }
        }else {
            //如果是出库,那就需要将之前仓库里的数量增加回来
            //通过入库单的id在出入库单据明细中,查找出哪些商品进行了入库
            List<StockBillVo> list = getBaseMapper().selectGoodsByBillId(id);
            for (StockBillVo stockBillVo : list) {
                //查询出当前仓库的库存数量
                Long number = getBaseMapper().selectGoodsInStore(storeId, stockBillVo);
                //如果数量够的话,就执行修改数量的操作
                Long sum = number + Long.parseLong(stockBillVo.getNumber());
                //根据物品的id所在仓库里面修改数量
                getBaseMapper().updateGoodsInStore(storeId, stockBillVo.getId(), sum);
            }
        }

        //设置入库单据状态
        stockBill.setStatus(-1);
        //修改出入库单据状态
        return super.updateById(stockBill);
    }

    /***
     * 保存一条出入库单信息,需要先保存出入库单信息,还需要保存关系表中的数据
     * 需要对仓库中的物品数量进行修改,当商品数量不够的时候出库的话,就提示武平库存数量不够无法出库
     * 当入库单作废的时候也需要减少相应的物品库存,如果当物品库存不足的时候,就无法减少物品库存
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = ServiceException.class)
    @Override
    public boolean save(StockBill entity) {

        //设置操作人
        entity.setOperatorId(SecurityUtils.getUserId());
        //设置操作时间
        entity.setOperateDate(new Date());

        //获取前端传来的参数,调用父类的保存方法保存
        boolean save = super.save(entity);

        //获取前端传来的数据获取物品的id,物品的价钱,数量
        StockBillVo[] goods = entity.getGoods();
        //遍历物品数组
        for (StockBillVo good : goods) {
            //调用mapper方法在关系表中增加关系
            //在出入库单据明细表中插入单据id,物品id,物品的价钱,数量
            getBaseMapper().insertRelationToGoods(entity, good);
            //需要增加仓库里面的物品的数量
            //根据物品的id查询出仓库物品的数量
            //获取仓库id
            Long storeId = entity.getStoreId();
            Long number = getBaseMapper().selectGoodsInStore(storeId, good);
            //判断number是否为空
            if (number == null) {
                //如果通过物品的id来查询物品,没有找到就,那么说明这个仓库里面没有该物品,需要将该物品存入仓库中
                getBaseMapper().insertGoodsInStore(storeId, good);

            } else {
                //如果有数量,那么就查询出仓库里面的物品数量,然后再将前端传来的物品数量进行相加
                //得到实际的数量
                Long sum = number + Long.parseLong(good.getNumber());
                //根据物品的id所在仓库里面修改数量
                getBaseMapper().updateGoodsInStore(storeId, good.getId(), sum);
            }
        }

        return save;
    }

    @Override
    public StockBill getById(Serializable id) {
        //通过前端传过来的出入库单据id,查找出出入库对象
        StockBill stockBill = super.getById(id);
        //判断是否为空
        if (stockBill == null){
            //提示找不到出入库单据
            throw new ServiceException("找不到出入库单据");
        }
        //在出入库单据明细中根据入库单据id找到本次单据各个物品信息
        List<StockBillVo> list = getBaseMapper().selectByStockBillId(stockBill.getId());

        StockBillVo[] stockBillVos = list.toArray(new StockBillVo[0]);

        //将得到集合设置给stockBill
        stockBill.setGoods(stockBillVos);

        return stockBill;
    }
}
